import base64
import logging
import secrets
import uuid
import pytz  # 导入pytz库以处理时区问题
from datetime import datetime, timedelta, timezone
from hashlib import sha256
from typing import Any, Optional

from sqlalchemy import func
from werkzeug.exceptions import Unauthorized

from configs import dify_config
from constants.languages import language_timezone_mapping, languages
from events.tenant_event import tenant_was_created
from extensions.ext_redis import redis_client
from libs.helper import RateLimiter, TokenManager
from libs.passport import PassportService
from libs.password import compare_password, hash_password, valid_password
from libs.rsa import generate_key_pair
from models.model import *
from models.model import DifySetup
from services.errors.account import (
    AccountAlreadyInTenantError,
    AccountLoginError,
    AccountNotLinkTenantError,
    AccountRegisterError,
    CannotOperateSelfError,
    CurrentPasswordIncorrectError,
    InvalidActionError,
    LinkAccountIntegrateError,
    MemberNotInTenantError,
    NoPermissionError,
    RateLimitExceededError,
    RoleAlreadyAssignedError
)
from tasks.mail_invite_member_task import send_invite_member_mail_task
from tasks.mail_reset_password_task import send_reset_password_mail_task
from flask_login import current_user

class CodeLogService:

    @staticmethod
    def list() -> list[CodeLog]:
        return db.session.query(CodeLog).order_by(CodeLog.created_at.desc()).all()

    @staticmethod
    def get_code_log_page(page: int, per_page: int) -> dict:
        """Get code log page"""
        query = CodeLog.query.order_by(CodeLog.created_at.desc()).paginate(page=int(page), per_page=per_page,error_out=False)
        codeLogs = []
        for item in query.items:
            codeLog = {
                'id': item.id,
                'type': item.type,
                'phone': item.phone,
                'code': item.code,
                'checked': item.checked,
                'status': item.status,
                'reason': item.reason,
                'remark': item.remark,
                'operator_id': item.operator_id,
                'ip': item.ip,
                'md5_key': item.md5_key,
                'send_time': item.send_time,
                'created_at': item.created_at.strftime("%Y-%m-%d %H:%M:%S"),
                'updated_at': item.updated_at.strftime("%Y-%m-%d %H:%M:%S")
            }
            codeLogs.append(codeLog)
        return {'result': 'success', 'codeLogs': codeLogs, 'total': query.total, 'per_page': per_page, 'page': page, 'pages': query.pages}


    @staticmethod
    def save(codeLog: CodeLog):
        db.session.add(codeLog)
        db.session.commit()


    @staticmethod
    def update(codeLog: CodeLog):
        db.session.update(codeLog)
        db.session.commit()

    @staticmethod
    def can_send(phone: str) -> str:
        today = datetime.now().date()
        codeLogs = db.session.query(CodeLog).filter(func.date(CodeLog.created_at) == today).filter(CodeLog.phone == phone).filter(CodeLog.type == '0').filter(CodeLog.status == '1').order_by(CodeLog.created_at.desc()).all()
        if len(codeLogs) >= 1:
            if datetime.now() <= codeLogs[0].created_at + timedelta(seconds=30):
                return '0'
            if len(codeLogs) >= 5:
                return '1'
        return '2'

    @staticmethod
    def check(phone: str, code: str) -> bool:
        today = datetime.now().date()
        codeLog = db.session.query(CodeLog).filter(func.date(CodeLog.created_at) == today).filter(CodeLog.phone == phone).filter(CodeLog.type == '0').filter(CodeLog.status == '1').order_by(CodeLog.created_at.desc()).first()
        if datetime.now() >= codeLog.created_at + timedelta(minutes=5):
            return  False
        if codeLog.code != code:
            return False
        return True

    @staticmethod
    def checked(phone: str):
        today = datetime.now().date()
        codeLog = db.session.query(CodeLog).filter(func.date(CodeLog.created_at) == today).filter(CodeLog.phone == phone).filter(CodeLog.type == '0').filter(CodeLog.status == '1').order_by(CodeLog.created_at.desc()).first()
        codeLog.status = '1'
        codeLog.checked = '1'
        db.session.add(codeLog)
        db.session.commit()





